/**
 编写程序，实现以下生产者-消费者问题：
 1. 有多个生产者(Productor)每间隔1秒将生产的一个产品交给店员(Clerk)
 2. 有多个消费者(Customer)每间隔1秒可以从店员处购买一个产品
 3. 一个店员最多能管理20个产品
 4. 如果店员管理的产品数量超过20个，店员会叫生产者停止生产
 5. 如果店员管理的产品数量低于20个，再通知生产者继续生产
 6. 如果店员中没有产品了，店员会告诉消费者等一下，当有产品时，通知消费者购买产品

 */
public class Test5 {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();

        // 创建3个生产者
        for (int i = 1; i <= 3; i++) {
            new Thread(new Producer(clerk), "生产者" + i).start();
        }

        // 创建3个消费者
        for (int i = 1; i <= 3; i++) {
            new Thread(new Consumer(clerk), "消费者" + i).start();
        }
    }
}

// 店员类，负责管理产品
class Clerk {
    private int productCount = 0;
    private static final int MAX_PRODUCT = 20;

    // 生产产品
    public synchronized void produceProduct() {
        while (productCount >= MAX_PRODUCT) {
            try {
                System.out.println("产品已满，生产者等待...");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        productCount++;
        System.out.println(Thread.currentThread().getName() + " 生产了1个产品，当前库存: " + productCount);
        notifyAll(); // 通知消费者可以购买
    }

    // 消费产品
    public synchronized void consumeProduct() {
        while (productCount <= 0) {
            try {
                System.out.println("产品已售罄，消费者等待...");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        productCount--;
        System.out.println(Thread.currentThread().getName() + " 购买了1个产品，当前库存: " + productCount);
        notifyAll(); // 通知生产者可以生产
    }
}

// 生产者类
class Producer implements Runnable {
    private Clerk clerk;

    public Producer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 开始生产产品...");
        while (true) {
            try {
                Thread.sleep(1000); // 每隔1秒生产一个产品
                clerk.produceProduct();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 消费者类
class Consumer implements Runnable {
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 开始购买产品...");
        while (true) {
            try {
                Thread.sleep(1000); // 每隔1秒购买一个产品
                clerk.consumeProduct();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

